package com.gupaoedu.vip.pattern.springmvc2.aop.intercept;

import com.gupaoedu.vip.pattern.springmvc2.aop.aspect.MyJoinPoint;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MyMethodInvocation implements MyJoinPoint {

    private Object proxy;

    private Object target;

    private Method method;

    private Object [] arguments;

    private Class<?> targetClass;

    private List<Object> interceptorsAndDynamicMethodMatchers;

    private int currentInterceptorIndex = -1;

    private Map<String,Object> userAttribute;

    public MyMethodInvocation(
            Object proxy, Object target, Method method, Object[] arguments,
            Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
        this.proxy = proxy;
        this.target = target;
        this.method = method;
        this.arguments = arguments;
        this.targetClass = targetClass;
        this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
    }

    public Object proceed() throws Throwable{
        if(this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()-1){
            return this.method.invoke(this.target, this.arguments);
        }
        Object interceptOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if(interceptOrInterceptionAdvice instanceof MyMethodInterceptor){
            MyMethodInterceptor mi = (MyMethodInterceptor) interceptOrInterceptionAdvice;
            return mi.invoke(this);
        }else{
            return proceed();
        }
    }

    public Object getThis() {
        return this.target;
    }

    public Object[] getArguments() {
        return this.arguments;
    }

    public Method getMethod() {
        return this.method;
    }

    public void setUserAttribute(String key, Object value) {
        if(value!=null){
            if(this.userAttribute == null){
                this.userAttribute = new HashMap<String, Object>();
            }
            this.userAttribute.put(key, value);
        }else{
            if(this.userAttribute!=null){
                this.userAttribute.remove(key);
            }
        }
    }

    public Object getUserAttribute(String key) {
        return (this.userAttribute != null?this.userAttribute.get(key):null);
    }
}
